\section{Persistência: JPA - Introdução}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{JPA: Setup do JBoss}
\begin{frame}
  \frametitle{Configurando o datasource no JBoss}
  \begin{itemize}
    \item O primeiro passo para a conexão com o banco de dados é a configuração
    no datasource. É preciso:
    \begin{itemize}
      \item Copiar o $driver$ JDBC (para derby, ``derbyclient.jar'') para o
      diretório $server/default/lib$ do JBoss
      \item Copiar a o XML com a definição do datasource para $server
      / default / deploy$
    \end{itemize}
    \item Inicialize o derby com o script ``startNetworkServer.bat''
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Arquivo de configuração do datasource}
  \begin{verbatim}
<datasources>
  <local-tx-datasource>
    <jndi-name>jdbc/testeDS</jndi-name>
    <use-java-context>false</use-java-context>
    <connection-url>
        jdbc:derby://localhost:1527/teste;create=true
    </connection-url>
    <driver-class>
      org.apache.derby.jdbc.ClientDriver
    </driver-class>
    <user-name>teste</user-name>
    <password>teste</password>
  </local-tx-datasource>
</datasources>
  \end{verbatim}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Configuração do projeto para uso do JPA}
  \begin{itemize}
    \item Em $src$, crie um diretório chamado $META-INF$ e o arquivo $persistence.xml$
    \begin{verbatim}
<persistence ...>
  <persistence-unit name="Teste2" 
                    transaction-type="RESOURCE_LOCAL">
    <non-jta-data-source>jdbc/testeDS</non-jta-data-source>
    <properties>
      <property name="hibernate.dialect" 
             value="org.hibernate.dialect.DerbyDialect" />
      <property name="hibernate.show_sql" 
                value="true" />
      <property name="hibernate.hbm2ddl.auto" 
                value="update"/>
    </properties>
  </persistence-unit>
</persistence>
    \end{verbatim}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Finalizando a configuração - Testes}
  \begin{itemize}
    \item Inicie o SGDB e o JBoss e certifique-se de que nenhum erro aparece
    nos logs
    \item Mapeie a entidade pessoa:
    \begin{itemize}
      \item Anote a classe com $Entity$ e a chave primária ($rg$) com $Id$:
    \end{itemize}
    \begin{verbatim}
    @Entity
    public class Pessoa {
        @Id
        private Integer rg;
    \end{verbatim}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Finalizando a configuração - Testes}
  \begin{itemize}
    \item No servlet, crie um atributo do tipo $EntityManagerFactory$ e anote com
    $@PersistenceUnit$:
    \begin{verbatim}
@PersistenceUnit
private EntityManagerFactory emf;
    \end{verbatim}
    \item No método doPost, invoque ``em.persist(pessoa);'' para criar a pessoa
    no banco:
    \begin{verbatim}
...
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(pessoa);
em.getTransaction().commit();
...
    \end{verbatim}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Verificando o objeto no banco}
  \begin{itemize}
    \item Invoque a tela já criada, preencha os dados e clique em criar
    \item Conecte no banco de dados e faça o select buscando os dados criados:
    \begin{itemize}
      \item Ferramenta para acessar o Derby: $ij.bat$ 
      \begin{verbatim}
connect 'jdbc:derby://localhost:1527/teste;';
select * from teste.Pessoa;
      \end{verbatim}
    \end{itemize} 
  \end{itemize}
\end{frame}

\subsection{Persistência com JPA}
\begin{frame}
  \frametitle{EntityManager}
  \begin{itemize}
    \item As operações (criação de objetos, execução de queries\ldots) são
    feitas pelo EntityManager
    \item Métodos do EntityManager:
    \begin{itemize}
      \item void persist(Object entity): Cria uma entidade na base (insert)
      \item T merge(T entity): Atualiza uma entidade (update)
      \item void remove(Object entity): Remove um objeto da base (delete)
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Métodos do EntityManager - cont.}
  \begin{itemize}
    \item Métodos do EntityManager:
    \begin{itemize}
      \item T find(Class entityClass, Object primaryKey): Busca um
      objeto pela chave primária. Retorna $null$ se o objeto não for encontrado
      \item Query createQuery(String qlString),
      \item Query createNativeQuery(String sqlString):
      \begin{itemize}
        \item Criam queries em SQL ou JPAQL
      \end{itemize}
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Métodos do EntityManager - cont.}
  \begin{itemize}
    \item Métodos do EntityManager:
    \begin{itemize}
      \item void close(): Deve ser invocado no término do uso do EntityManager
      (quando criado com EntityManagerFactory)
      \item EntityTransaction getTransaction(): Retorna objeto para controle de
      transação
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Mapeamento OR: Anotações}
  \begin{itemize}
    \item O mapeamento objeto-relacional é feito por meio de anotações nas
    classes JavaBean e nos seus atributos
    \item Anotações JPA:
    \begin{itemize}
      \item @Entity: Indica que a classe é uma entidade
      \item @Table: Usada em conjunto com @Entity, especifica informações
      específicas da tabela a ser mapeada
      \begin{itemize}
        \item name: Nome da tabela. Por padrão, é o nome da classe
        \item catalog, schema: Namespace no banco
      \end{itemize}
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Mapeamento OR: Anotações - cont.}
  \begin{itemize}
    \item Anotações JPA:
    \begin{itemize}
      \item @Id: Indica que um campo é chave primária
      \item @Column: Usada nos atributos. Informações da coluna:
      \begin{itemize}
        \item name: Nome da coluna. Por padrão é o mesmo do atributo
        \item unique: Se valores repeditos na tabela são permitidos
        \item nullable: Se aceita $null$
        \item length: Comprimento da string. Padrão: $255$
        \item precision, scale: Para valores decimais
      \end{itemize}
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Mapeamento OR: Anotações - cont.}
  \begin{itemize}
    \item Anotações JPA:
    \begin{itemize}
      \item @GeneratedValue: Atributo gerado automaticamente (auto, sequence,
      etc\ldots)
      \begin{verbatim}
@Id
@GeneratedValue(strategy=AUTO)
private Long id;
      \end{verbatim}
      \item @Transient: Atributo não é mapeado ao banco
      \item @Lob: Campo blob
      \item @Temporal e TemporalType: Campos de data/hora
    \end{itemize}
  \end{itemize}
\end{frame}

\subsection{Queries com JPA}
\begin{frame}[fragile]
  \frametitle{Exercício}
  \begin{itemize}
    \item Faça uma tela que liste todas as pessoas criadas no banco
    \item Passos para a criação dessa tela:
    \begin{itemize}
      \item Criar um novo servlet: ListarPessoalServlet (com doGet e
      EntityManagerFactory)
      \item Faça uma consulta usando uma Querty do JPA:
      \begin{verbatim}
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Query query = em.createQuery(
        "select pessoa from Pessoa pessoa");
List pessoas = query.getResultList();
request.setAttribute("pessoas", pessoas);
em.getTransaction().commit();
request.getRequestDispatcher("/pessoas.jsp")
           .forward(request, response);
      \end{verbatim}
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Exercício}
  \begin{itemize}
    \item Crie uma tela para testar a query: pessoas.jsp:
    \begin{verbatim}
Pessoas: ${requestScope.pessoas}
    \end{verbatim}
    \item Todas as pessoas da base devem ser exibidas na lista (baseado na
    saído do método toString)
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{JPAQL}
  \begin{itemize}
    \item Linguagem para queries bastante semelhante à SQL
    \item Utilize os nomes das CLASSES e não das TABELAS
    \item Exemplos:
    \begin{itemize}
      \item select p from Pessoa p
      \item select p from Pessoa p where p.rg = $324569876$
      \item select p.nome, p.idade from Pessoa p
      \item select distinct p.idade from Pessoa p
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{JPAQL - cont.}
  \begin{itemize}
    \item Exemplos:
    \begin{itemize}
      \item select e from Endereco e, Pessoa p where p.rg = e.idPessoa
      \item select count(p.rg), p.idade from Pessoa p group by p.idade
      \item delete from Pessoa p where p.rg = :parametroRG
      \item update Pessoa p ser p.nome=``Teste'' where p.rg = :parametroRG
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{JPAQL - Interface Query}
  \begin{itemize}
    \item As queries são executadas (e os resultados obtidos) da interface Query
    \item Métodos:
    \begin{itemize}
      \item List getResultList(): Retorna lista com resultado do select
      \item Object getSingleResult(): Retorna resultado único do select (o
      resultado do select deve ser único (e.g. busca envolvendo chave
      primária)). Lança exceção se o número de resultados for diferente de uma
      linha (se for zero ou maior que um)
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{JPAQL - Resultados dos selects}
  \begin{itemize}
    \item Diferentes tipos de objetos são retornados dependendo de como a query
    foi escrita:
    \begin{itemize}
      \item $select~p~from~Pessoa$: Lista de objetos ``Pessoa''
      \item $select~p.rg~from~Pessoa$: Lista de objetos ``Integer''
      \item $select~p.rg,~p.nome~from~Pessoa$: Lista de arrays com ``Integer''
      no primeiro elemento e ``String'' no segundo
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{JPAQL - Interface Query - cont.}
  \begin{itemize}
    \item Métodos:
    \begin{itemize}
      \item int executeUpdate(): Executa um update ou delete. Retorna o número
      de registros atualizados ou removidos
      \item setParameter(String name, Object value): Registra o valor de um
      parâmetro:
      \begin{verbatim}
Query query = em.createQuery(
            "select p from Pessoa p where p.nome = :nome");
query.setParameter("nome", request.getParameter("nome"));
List pessoas = query.getResultList();
      \end{verbatim}
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Exercício}
  \begin{itemize}
    \item Defina mais restrições na tabela pessoa (e.g. CHN deve ser nullable,
    etc\ldots)
    \item Mapeie a entidade Endereço
    \item Execute queries com Pessoa e Endereço
  \end{itemize}
\end{frame}
